package com.mainbo.androidframework.persistence.db.dao;

import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;


import com.mainbo.androidframework.persistence.db.DbException;

import java.util.ArrayList;
import java.util.List;

/**
 * <b>create time</b> 2015/5/26
 *
 * @author weilh
 */
public abstract class BaseDao<T> {
    protected SQLiteDatabase db;

    public void setDb(SQLiteDatabase db) {
        this.db = db;
    }

    public abstract String getTableName();

    public abstract T cursorToClass(Cursor cursor);

    public abstract ContentValues getContentValues(T object);

    /**
     *
     * @param object
     */
    public void saveOrUpdate(T object) throws DbException {
        if (object == null) return;
        try {
            db.beginTransaction();
            insertWithoutTran(object);
            db.setTransactionSuccessful();
        } finally {
            db.endTransaction();
        }
    }

    public void insertWithoutTran(T object) throws DbException {
        try {
            db.replace(getTableName(), null, getContentValues(object));
        } catch (Throwable e) {
            throw new DbException(e);
        }
    }

    /**

     * @param list update list
     */
    public void saveOrUpdateAll(List<T> list) throws DbException {
        if (list == null) return;
        db.beginTransaction();
        try {
            for (T object : list) {
                insertWithoutTran(object);
            }
            db.setTransactionSuccessful();
        } finally {
            db.endTransaction();
        }
    }

    public void saveOrUpdateAllWithoutTran(List<T> list) throws DbException {
        if (list == null) return;
        try {
            for (T object : list) {
                insertWithoutTran(object);
            }
        } finally {
        }
    }


    /**
     * delete one data
     */
    public void delete(String whereClause, String[] whereArg) throws DbException {
        try {
            db.beginTransaction();
            deleteWithoutTran(whereClause, whereArg);
            db.setTransactionSuccessful();
        } finally {
            db.endTransaction();
        }
    }

    public void deleteWithoutTran(String whereClause, String[] whereArgs) throws DbException {
        try {
            db.delete(getTableName(), whereClause, whereArgs);
        } catch (Throwable e) {
            throw new DbException(e);
        }
    }

    /**
     * delete all data in table
     */
    public void deleteAll() throws DbException {
        delete("1", null);
    }

    public void deleteAllWithoutTran() throws DbException {
        deleteWithoutTran("1", null);
    }

    /**
     * find all data in db
     *
     * @return List
     */
    public List<T> findAll() throws DbException {
        String sql = "select * from " + getTableName();
        return findAllBySql(sql);
    }

    public void execSQL(String sql, Object... args) throws DbException {
        try {
            db.beginTransaction();
            db.execSQL(sql, args);
            db.setTransactionSuccessful();
        } catch (Throwable e) {
            throw new DbException(e);
        } finally {
            db.endTransaction();
        }
    }

    public void execSQLWithoutTran(String sql, Object... args) throws DbException {
        try {
            db.execSQL(sql, args);
        } catch (Throwable e) {
            throw new DbException(e);
        }
    }

    /**
     * return object by sql
     *
     * @param sql sql
     * @return 对象
     */
    public T findBySql(String sql, String... args) throws DbException {
        Cursor cursor;
        T obj = null;
        try {
            cursor = db.rawQuery(sql, args);
            if (cursor != null) {
                if (cursor.moveToNext()) {
                    obj = cursorToClass(cursor);
                }
                cursor.close();
            }
        } catch (Throwable e) {
            throw new DbException(e);
        }
        return obj;
    }

    /**
     * return object list by sql
     *
     * @param sql sql
     * @return 对象列表
     */
    public List<T> findAllBySql(String sql, String... args) throws DbException {
        Cursor cursor;
        List<T> objList = new ArrayList<T>();
        try {
            cursor = db.rawQuery(sql, args);
            if (cursor != null) {
                while (cursor.moveToNext()) {
                    objList.add(cursorToClass(cursor));
                }
                cursor.close();
            }
        } catch (Throwable e) {
            throw new DbException(e);
        }
        return objList;
    }

    public List<Integer> getIntListBySql(String sql, String... args) throws DbException {
        Cursor cursor;
        List<Integer> list = new ArrayList<Integer>();
        try {
            cursor = db.rawQuery(sql, args);
            if (cursor != null) {
                while (cursor.moveToNext()) {
                    list.add(cursor.getInt(0));
                }
                cursor.close();
            }
        } catch (Throwable e) {
            throw new DbException(e);
        }
        return list;
    }

    protected int getIntBySql(String sql, String... args) throws DbException {
        int count = 0;
        try {
            Cursor cursor = db.rawQuery(sql, args);
            if (cursor != null) {
                if (cursor.moveToNext()) {
                    count = cursor.getInt(0);
                }
                cursor.close();
            }
        } catch (Throwable e) {
            throw new DbException(e);
        }
        return count;
    }

    public List<String> getStrListBySql(String sql, String... args) throws DbException {
        Cursor cursor;
        List<String> list = new ArrayList<String>();
        try {
            cursor = db.rawQuery(sql, args);
            if (cursor != null) {
                while (cursor.moveToNext()) {
                    list.add(cursor.getString(0));
                }
                cursor.close();
            }
        } catch (Throwable e) {
            throw new DbException(e);
        }
        return list;
    }

    protected String getStrBySql(String sql, String... args) throws DbException {
        String result = null;
        try {
            Cursor cursor = db.rawQuery(sql, args);
            if (cursor != null) {
                if (cursor.moveToNext()) {
                    result = cursor.getString(0);
                }
                cursor.close();
            }
        } catch (Throwable e) {
            throw new DbException(e);
        }
        return result;
    }

    /**
     * @param info extension message
     * @param e    Exception
     * @return string
     */
    public String getDebugInfo(String info, Exception e) {
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("  targetClassName : " + getTableName());
        stringBuilder.append("  info :" + info);
        stringBuilder.append(" exception : " + e.toString() + "  " + e.getMessage());
        return stringBuilder.toString();
    }
}
